package com.luhuiguo.cms.server.webdav;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Map;

import org.apache.commons.io.IOUtils;
import org.apache.commons.vfs.FileObject;
import org.apache.commons.vfs.FileSystemException;
import org.apache.commons.vfs.FileUtil;
import org.apache.commons.vfs.RandomAccessContent;
import org.apache.commons.vfs.util.RandomAccessMode;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.bradmcevoy.http.Auth;
import com.bradmcevoy.http.CollectionResource;
import com.bradmcevoy.http.FileItem;
import com.bradmcevoy.http.FileResource;
import com.bradmcevoy.http.Range;
import com.bradmcevoy.http.exceptions.ConflictException;
import com.bradmcevoy.http.exceptions.NotAuthorizedException;

/**
 * 
 * @author LuHuiguo
 * @version $Id: GaeFileResource.java 176 2010-05-17 09:22:49Z
 *          luhuiguo@gmail.com $
 */
public class GaeFileResource extends GaeResource implements FileResource {

    private static final Logger logger = LoggerFactory.getLogger(GaeFileResource.class);

    public GaeFileResource(String host, GaeResourceFactory factory, FileObject fileObject) {
        super(host, factory, fileObject);

    }

    @Override
    public Long getContentLength() {
        try {
            if (!fileObject.exists())
                return null;
            return fileObject.getContent().getSize();
        } catch (FileSystemException e) {
            logger.warn(e.getMessage(), e);
            // e.printStackTrace();
            return null;
        }
    }

    @Override
    public String getContentType(String accepts) {
        try {
            if (!fileObject.exists()) {
                return null;
            }
            return (String) fileObject.getContent().getAttribute("mime-type");
        } catch (FileSystemException e) {
            logger.warn(e.getMessage(), e);
            // e.printStackTrace();
            return "application/octet-stream";
        }
    }

    @Override
    public Long getMaxAgeSeconds(Auth auth) {
        return factory.maxAgeSeconds(this);
    }

    @Override
    public void sendContent(OutputStream out, Range range, Map<String, String> params, String contentType)
            throws IOException, NotAuthorizedException {
        if (range != null) {
            logger.debug("Sending range content! params={}, type={}", params, contentType);
            final RandomAccessContent random = fileObject.getContent().getRandomAccessContent(RandomAccessMode.READ);
            random.seek(range.getStart());
            final InputStream input = random.getInputStream();
            IOUtils.copy(input, out);
        } else {
            logger.debug("Sending content! params={}, type={}", params, contentType);

            final InputStream input = fileObject.getContent().getInputStream();
            try {
                IOUtils.copy(input, out);
                out.close();
                input.close();
            } catch (IOException ex) {
                logger.warn("Send ended early!", ex);
                try {
                    input.close();
                } catch (IOException e) {
                    // e.printStackTrace();
                    logger.warn("ERROR closing inputstream!", e);
                }
            }
        }
    }

    @Override
    public String processForm(Map<String, String> parameters, Map<String, FileItem> files) {
        logger.debug("process form!");
        return null;
    }

    @Override
    public void copyTo(CollectionResource toCollection, String name) {
        logger.debug("Copying file! dest={}, name={}", toCollection.getName(), name);
        try {
            if (toCollection instanceof GaeDirectoryResource) {
                final FileObject destFile = ((GaeDirectoryResource) toCollection).fileObject.resolveFile(name);
                FileUtil.copyContent(fileObject, destFile);
            } else {
                throw new IOException("Wrong resource type");
            }
        } catch (IOException e) {
            logger.warn(e.getMessage(), e);
            // e.printStackTrace();
        }
    }

    @Override
    public void moveTo(CollectionResource rDest, String name) throws ConflictException {
        logger.debug("Moving file! dest={}, name={}", rDest.getName(), name);
        try {
            if (rDest instanceof GaeDirectoryResource) {
                final FileObject destFile = ((GaeDirectoryResource) rDest).fileObject.resolveFile(name);
                if (!fileObject.canRenameTo(destFile)) {
                    throw new ConflictException(rDest.child(name));
                }
                fileObject.moveTo(destFile);
            } else {
                throw new IOException("Wrong resource type");
            }
        } catch (IOException e) {
            logger.warn(e.getMessage(), e);
            // e.printStackTrace();
        }
    }
}
